package me.yuzho.study.concurrency;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;

//正常的锁,来自concurrent.locks或内建的synchronized锁，有任何时候都只允许一个任务访问一项资源
// 而计数信号量Semaphore允许n个任务同时访问这个资源

// Using a Semaphore inside a Pool, to restrict the number of tasks that can use a resource


public class Pool<T> {
    
    private int size;
    private List<T> items = new ArrayList<T>();
    private volatile boolean[] checkedOut;
    private Semaphore available;
    
    public Pool(Class<T> classObject, int size) {
        this.size = size;
        checkedOut = new boolean[size];
        available = new Semaphore(size, true);
        
        // Load pool with objects that can be checked out
        for(int i=0; i < size; i++) {
            try {
                items.add(classObject.newInstance());
            } catch (Exception e) {
                throw new RuntimeException(e);
            } 
        }
    }
    
    public T checkOut() throws InterruptedException {
        available.acquire();
        return getItem();
    }
    
    public void checkIn(T x) {
        if(releaseItem(x)) {
            available.release();
        }
    } 

    private synchronized boolean releaseItem(T item) {
        int index = items.indexOf(item);
        if(index == -1) return false; 
        if(checkedOut[index]) {
            checkedOut[index] = false;
            return true;
        }
        return false; // Wasn't checked out
    }

    private synchronized T getItem() {
        for(int i=0; i<size; ++i) {
            if(!checkedOut[i]) {
                checkedOut[i] = true;
                return items.get(i);
            }
        }
        return null; //Semaphore prevents reaching here
    }

}
